<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <script>
      // 菜单列表
      const menuList = [
        {
          name: "系统管理",
          code: "system_manage",
          children: [
            {
              name: "用户管理",
              code: "user_manage",
              children: [
                {
                  name: "添加用户",
                  code: "add_user",
                },
                {
                  name: "编辑用户",
                  code: "edit_user",
                },
                {
                  name: "删除用户",
                  code: "del_user",
                },
              ],
            },
            {
              name: "角色管理",
              code: "role_manage",
              children: [
                {
                  name: "添加角色",
                  code: "add_role",
                },
              ],
            },
          ],
        },
        {
          name: "业务管理",
          code: "bus_manage",
          children: [
            {
              name: "流程管理",
              code: "process_manage",
            },
          ],
        },
        {
          name: "订单管理",
          code: "order_manage",
        },
      ];

      // 权限列表
      const myMenuCode = [
        "add_user",
        "process_manage",
        "add_role",
        "order_manage",
      ];
      // const myMenuCode = ['system_manage', 'user_manage', 'add_user', 'bus_manage', 'order_manage']

      // 这个情形里面，递归的主要是根据一个条件筛选树形结构的数据，但是不能修改数据的结构，他必须还是树形的，类似于树组件的过滤
      // 根据权限列表去过滤菜单列表，要求如果子级符合标准，就保留它的父级
      function filterMenuByPermission(menu, permissionList) {
        return menu.filter((item) => {
          // 判断当前菜单项是否在权限列表中
          if (permissionList.includes(item.code)) {
            // 如果有子菜单，递归过滤子菜单并保留符合条件的父菜单
            if (item.children && item.children.length > 0) {
              item.children = filterMenuByPermission(
                item.children,
                permissionList
              );
            }
            return true;
          } else if (item.children && item.children.length > 0) {
            // 如果没有权限但有子菜单，递归过滤子菜单并保留符合条件的父菜单
            item.children = filterMenuByPermission(
              item.children,
              permissionList
            );
            // 判断的依据就是如果子菜单的长度大于0，就表明它的子级中有符合要求的，那它就可以保留
            return item.children.length > 0;
          }
          // 其他情况不符合条件
          return false;
        });
      }

      const filteredMenu = filterMenuByPermission(menuList, myMenuCode);
      console.log(filteredMenu);

      // 改为使用map方法，总的来说没有filter方法使用起来丝滑
      function filterMenu(menuList, menuCode) {
        let menus = JSON.parse(JSON.stringify(menuList));
        let menu = [];
        menus.map((item) => {
          if (menuCode.includes(item.code)) {
            if (item.children && item.children.length > 0) {
              item.children = filterMenu(item.children, menuCode);
            }
            menu.push(item);
          } else if (item.children && item.children.length > 0) {
            item.children = filterMenu(item.children, menuCode);
            if (item.children.length > 0) {
              menu.push(item);
            }
          }
        });
        return menu;
      }
      // 过滤后的菜单
      const myMenu = filterMenu(menuList, myMenuCode);
      console.log(myMenu);

      // 一个根据子级id查找所有父级路径的方法
      // 查找父级
      function findParentNode(list, id) {
        for (let i in list) {
          if (list[i].id === id) {
            let obj = cloneDeep(list[i]);
            // unset(obj, "children");
            return [obj];
          }
          if (list[i].children && list[i].children.length > 0) {
            let node = this.findParentNode(list[i].children, id);
            if (node !== undefined) {
              let obj = cloneDeep(list[i]);
              // unset(obj, "children");
              return node.concat(obj);
            }
          }
        }
      }
    </script>
  </body>
</html>
